1 using UnityEngine;
2 using ThreeDPool.EventHandlers;
3 using ThreeDPool.Managers;
4
5 namespace ThreeDPool.Controllers
6 {
7 public class CameraController : MonoBehaviour
8 {
9 [SerializeField]
10 private Transform _cueBall = null;
11
12 // distance from the cue ball
13 private float _distFromCueBall;
14
15 private Vector3 _initialPos;
16 private Vector3 _initialDir;
17
18 // this is the position to rotate around when the ball is been striked to stationary
19 // the default value for this vector should be one to avoid unexpected behavior
20 private Vector3 _posToRot = Vector3.one;
21
22 // Use this for initialization
23 private void Start()
24 {
25 // cache the initial position and rotation
26 _initialPos = transform.position;
27 _initialDir = transform.forward;
28
29 // making sure the distance is same as what we started with
30 _distFromCueBall = Vector3.Distance(_cueBall.position, transform.position);
31
32 // subscribe for events
33 EventManager.Subscribe(typeof(GameInputEvent).Name, OnGameInputEvent);
34 EventManager.Subscribe(typeof(CueBallActionEvent).Name, OnCueBallEvent);
35 EventManager.Subscribe(typeof(GameStateEvent).Name, OnGameStateEvent);
36 }
37
38 private void OnDestroy()
39 {
40 // unsubscribe for events
41 EventManager.Unsubscribe(typeof(GameInputEvent).Name, OnGameInputEvent);
42 EventManager.Unsubscribe(typeof(CueBallActionEvent).Name, OnCueBallEvent);
43 EventManager.Unsubscribe(typeof(GameStateEvent).Name, OnGameStateEvent);
44 }
45
46 // handle camera action based on the cue ball event
47 private void OnCueBallEvent(object sender, IGameEvent gameEvent)
48 {
49 CueBallActionEvent cueBallActionEvent = (CueBallActionEvent)gameEvent;
50
51 switch (cueBallActionEvent.State)
52 {
53 case CueBallActionEvent.States.Stationary:
54 case CueBallActionEvent.States.Default:
55 {
56 float yPos = transform.position.y;
57
58 // move the camera closer to the cue ball
59 transform.position = _cueBall.transform.position - transform.forward * _distFromCueBall;
60 transform.position = new Vector3(transform.position.x, yPos, transform.position.z);
61
62 // keep looking at the cue ball
63 transform.LookAt(_cueBall);
64
65 // reset the pos to rot vector
66 _posToRot = Vector3.one;
67 }
68 break;
69 case CueBallActionEvent.States.Striked:
70 {
71 _posToRot = _cueBall.transform.position;
72 }
73 break;
74 }
75 }
76
77 private void OnGameInputEvent(object sender, IGameEvent gameEvent)
78 {
79 GameInputEvent gameInputEvent = (GameInputEvent)gameEvent;
80
81 switch (gameInputEvent.State)
82 {
83 case GameInputEvent.States.HorizontalAxisMovement:
84 {
85 if (_posToRot == Vector3.one)
86 {
87 // start rotating camera around the ball
88 transform.RotateAround(_cueBall.position, Vector3.up, 20f * gameInputEvent.axisOffset * Time.deltaTime);
89 }
90 else
91 {
92 // start rotating camera around _posToRot vector
93 transform.RotateAround(_posToRot, Vector3.up, 20f * gameInputEvent.axisOffset * Time.deltaTime);
94 }
95 }
96 break;
97 case GameInputEvent.States.VerticalAxisMovement:
98 {
99 // nothing is done here for now
100 }
101 break;
102 }
103 }
104
105 private void OnGameStateEvent(object sender, IGameEvent gameEvent)
106 {
107 GameStateEvent gameStateEvent = (GameStateEvent)gameEvent;
108 switch (gameStateEvent.GameState)
109 {
110 case GameStateEvent.State.Play:
111 {
112 PlaceInInitialPosAndRot();
113 }
114 break;
115 }
116 }
117
118 private void PlaceInInitialPosAndRot()
119 {
120 _posToRot = Vector3.one;
121
122 transform.position = _initialPos;
123 transform.forward = _initialDir;
124 }
125 }
126 }